package com.ruoyi.loan.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.ComponentConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanTransUtils;
import com.ruoyi.loan.domain.CustomerAllocation;
import com.ruoyi.loan.domain.CustomerInfo;
import com.ruoyi.loan.domain.CustomerSnapshot;
import com.ruoyi.loan.domain.reponse.CustomerFollowResponse;
import com.ruoyi.loan.domain.reponse.CustomerInfoResponse;
import com.ruoyi.loan.domain.request.CustomerInfoRequest;
import com.ruoyi.loan.domain.request.CustomerRequest;
import com.ruoyi.loan.mapper.CustomerInfoMapper;
import com.ruoyi.loan.service.ICustomerAllocationService;
import com.ruoyi.loan.service.ICustomerInfoService;
import com.ruoyi.loan.service.ICustomerSnapshotService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 客户Service业务层处理
 *
 * @author ruoyi
 * @date 2023-03-18
 */
@Service
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo> implements ICustomerInfoService {

    @Autowired
    private BeanTransUtils beanTransUtils;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ICustomerAllocationService customerAllocationService;

    @Autowired
    private ICustomerSnapshotService customerSnapshotService;

    private List<String> changeColumnList = Lists.newArrayList();

    @Override
    public List<CustomerInfoResponse> getList(CustomerInfoRequest request) {
        LambdaQueryWrapper<CustomerInfo> wrapper = Wrappers.<CustomerInfo>lambdaQuery()
                .eq(StringUtils.isNotBlank(request.getLevel()),CustomerInfo::getLevel, request.getLevel())
                .eq(StringUtils.isNotBlank(request.getStatus()),CustomerInfo::getStatus, request.getStatus())
                .like(ObjectUtil.isNotNull(request.getPhoneNumber()),CustomerInfo::getPhoneNumber, request.getPhoneNumber())
                .like(StringUtils.isNotBlank(request.getName()),CustomerInfo::getName, request.getName())
                .ge(ObjectUtil.isNotNull(request.getBeginTime()),CustomerInfo::getCreateTime, request.getBeginTime())
                .le(ObjectUtil.isNotNull(request.getEndTime()),CustomerInfo::getCreateTime, request.getEndTime())
                .and(StringUtils.equals(request.getHasCar(), "1"), t -> t.isNotNull(CustomerInfo::getCarJson).ne(CustomerInfo::getCarJson, "[]"))
                .and(StringUtils.equals(request.getHasCar(), "0"), t -> t.isNull(CustomerInfo::getCarJson).or().eq(CustomerInfo::getCarJson, "[]"))
                .and(StringUtils.equals(request.getHasInsurance(), "1"), t -> t.isNotNull(CustomerInfo::getInsuranceJson).ne(CustomerInfo::getInsuranceJson, "[]"))
                .and(StringUtils.equals(request.getHasInsurance(), "0"), t -> t.isNull(CustomerInfo::getInsuranceJson).or().eq(CustomerInfo::getInsuranceJson, "[]"))
                .and(StringUtils.equals(request.getHasHouse(), "1"), t -> t.isNotNull(CustomerInfo::getHouseJson).ne(CustomerInfo::getHouseJson, "[]"))
                .and(StringUtils.equals(request.getHasHouse(), "0"), t -> t.isNull(CustomerInfo::getHouseJson).or().eq(CustomerInfo::getHouseJson, "[]"))
                .ge(ObjectUtil.isNotNull(request.getStartLoanRange()),CustomerInfo::getAmount, request.getStartLoanRange())
                .le(ObjectUtil.isNotNull(request.getEndLoanRange()),CustomerInfo::getAmount, request.getEndLoanRange())
                .like(StringUtils.isNotBlank(request.getRemark()),CustomerInfo::getRemark, request.getRemark())
                .orderByAsc(CustomerInfo::getFollowCustomer)
                .orderByAsc(CustomerInfo::getFollowRemind)
                .orderByAsc(CustomerInfo::getFollowRepayment)
                .orderByDesc(CustomerInfo::getId);
        this.dealCustomerInfoType(wrapper, request.getType());
        List<CustomerInfo> list = this.baseMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(list)) {
            List<CustomerInfoResponse> responseList = this.beanTransUtils.beanListTransform(list, CustomerInfoResponse.class);
            List<SysUser> sysUserList = this.sysUserService.list();
            Map<Long, SysUser> userMap = sysUserList.stream().collect(Collectors.toMap(SysUser::getUserId, t -> t, (o1, o2) -> o1));
            responseList.forEach(t -> {
                t.setHandleUserString(ObjectUtil.isNotNull(t.getHandleUser()) ? ObjectUtil.isNotNull(userMap.get(t.getHandleUser())) ? userMap.get(t.getHandleUser()).getNickName() : "-" : "-");
                t.setLoanUserString(ObjectUtil.isNotNull(t.getLoanUser()) ? ObjectUtil.isNotNull(userMap.get(t.getLoanUser())) ? userMap.get(t.getLoanUser()).getNickName() : "-" : "-");
                t.setAfterUserString(ObjectUtil.isNotNull(t.getAfterUser()) ? ObjectUtil.isNotNull(userMap.get(t.getAfterUser())) ? userMap.get(t.getAfterUser()).getNickName() : "-" : "-");
            });
            return responseList;
        }
        return Lists.newArrayList();
    }

    @Override
    public void edit(CustomerInfo customerInfo) {
        CustomerInfo oldCustomerInfo = this.baseMapper.selectById(customerInfo.getId());
        if (this.checkField(oldCustomerInfo, customerInfo)) {
            CustomerSnapshot customerSnapshot = beanTransUtils.beanTransform(oldCustomerInfo, CustomerSnapshot.class);
            customerSnapshot.setId(null);
            customerSnapshot.setCustomerInfoId(customerInfo.getId());
            this.customerSnapshotService.saveOrUpdate(customerSnapshot);
        }
        this.baseMapper.updateById(customerInfo);

    }

    private boolean checkField(CustomerInfo oldCustomerInfo, CustomerInfo customerInfo) {
        boolean flag = false;
        for (String column : DictUtils.getColumnList()) {
            Object oldObject = BeanUtil.getProperty(oldCustomerInfo, column);
            Object object = BeanUtil.getProperty(customerInfo, column);
            if (!StringUtils.equals(String.valueOf(oldObject), String.valueOf(object))) {
                flag = true;
            }
        }
        return flag;


    }

    @Override
    public void dealCustomerInfoType(LambdaQueryWrapper<CustomerInfo> wrapper, Integer type) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        switch (type) {
            //公共售前池
            case 1 :
                wrapper.isNull(CustomerInfo::getHandleUser).or().eq(CustomerInfo::getHandleUser, "");
                break;
            //我的售前池
            case 2 :
                wrapper.eq(CustomerInfo::getHandleUser, SecurityUtils.getUserId());
                break;
            //我的后期池
            case 3 :
                wrapper.eq(CustomerInfo::getLoanUser, SecurityUtils.getUserId());
                wrapper.eq(CustomerInfo::getLoanStatus, "1");
                break;
            //我的售后池
            case 4 :
                wrapper.eq(CustomerInfo::getAfterUser, SecurityUtils.getUserId());
                wrapper.eq(CustomerInfo::getAfterSaleStatus, "1");
                break;
            //团队售前池
            case 5 :
                wrapper.in(!SecurityUtils.isSuperAdmin(loginUser), CustomerInfo::getHandleUser, loginUser.getBelongUserIds());
                break;
            //团队后期池
            case 6 :
                wrapper.in(!SecurityUtils.isSuperAdmin(loginUser), CustomerInfo::getLoanUser, loginUser.getBelongUserIds());
                wrapper.eq(CustomerInfo::getLoanStatus, "1");
                break;
            //团队售后池
            case 7 :
                wrapper.in(!SecurityUtils.isSuperAdmin(loginUser), CustomerInfo::getAfterUser, loginUser.getBelongUserIds());
                wrapper.eq(CustomerInfo::getAfterSaleStatus, "1");
                break;
            //待确认至后期
            case 8 :
                wrapper.in(!SecurityUtils.isSuperAdmin(loginUser), CustomerInfo::getHandleUser, loginUser.getBelongUserIds());
                wrapper.eq(CustomerInfo::getLoanStatus, "2");
                break;
            //待确认至售后
            case 9 :
                wrapper.in(!SecurityUtils.isSuperAdmin(loginUser), CustomerInfo::getLoanUser, loginUser.getBelongUserIds());
                wrapper.eq(CustomerInfo::getAfterSaleStatus, "2");
                break;
        }
    }

    @Override
    public void followCustomer(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getFollowCustomer, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public void followRemind(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getFollowRemind, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public void followRepayment(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getFollowRepayment, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public void claimCustomer(CustomerRequest request) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        List<Long> userIds = customerInfoList.stream().map(CustomerInfo::getHandleUser).filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        userIds.add(loginUser.getUserId());
        Map<Long, String> userNickNameMap = this.sysUserService.getNickNameMap(userIds);
        List<CustomerAllocation> customerAllocationList = Lists.newArrayList();
        customerInfoList.forEach(t -> {
            t.setHandleUser(loginUser.getUserId());
            t.setFollowCustomer(99);
            CustomerAllocation customerAllocation = new CustomerAllocation();
            this.baseMapper.updateById(t);
            customerAllocationList.add(customerAllocation);
            customerAllocation.setCustomerInfoId(t.getId());
            customerAllocation.setRecipientId(loginUser.getUserId());
            customerAllocation.setType(0);
            customerAllocation.setRemark(t.getName() + "分配给售前：" + userNickNameMap.get(loginUser.getUserId()));
        });
        this.customerAllocationService.saveOrUpdateBatch(customerAllocationList);

    }

    @Override
    public void distCustomer(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        List<Long> userIds = customerInfoList.stream().map(CustomerInfo::getHandleUser).filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        userIds.add(request.getUserId());
        Map<Long, String> userNickNameMap = this.sysUserService.getNickNameMap(userIds);
        List<CustomerAllocation> customerAllocationList = Lists.newArrayList();
        customerInfoList.forEach(t -> {
            t.setHandleUser(request.getUserId());
            t.setFollowCustomer(0);
            CustomerAllocation customerAllocation = new CustomerAllocation();
            this.baseMapper.updateById(t);
            customerAllocationList.add(customerAllocation);
            customerAllocation.setCustomerInfoId(t.getId());
            customerAllocation.setRecipientId(request.getUserId());
            customerAllocation.setType(0);
            customerAllocation.setRemark(t.getName() + "分配给售前：" + userNickNameMap.get(request.getUserId()));
        });
        this.customerAllocationService.saveOrUpdateBatch(customerAllocationList);

    }

    @Override
    public void publicDist(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getHandleUser, null)
                    .set(CustomerInfo::getSigningStatus, 0)
                    .set(CustomerInfo::getAfterSaleStatus, 0)
                    .set(CustomerInfo::getFollowCustomer, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public void stateToLoan(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        customerInfoList.forEach(t -> {
            t.setLoanStatus(2);
            t.setFollowCustomer(1);
            this.baseMapper.updateById(t);
        });

    }

    @Override
    public void distLoan(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        List<Long> userIds = customerInfoList.stream().map(CustomerInfo::getHandleUser).filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        userIds.add(request.getUserId());
        Map<Long, String> userNickNameMap = this.sysUserService.getNickNameMap(userIds);
        List<CustomerAllocation> customerAllocationList = Lists.newArrayList();
        customerInfoList.forEach(t -> {
            t.setLoanUser(request.getUserId());
            t.setLoanStatus(1);
            t.setFollowCustomer(2);
            this.baseMapper.updateById(t);
            CustomerAllocation customerAllocation = new CustomerAllocation();
            customerAllocationList.add(customerAllocation);
            customerAllocation.setCustomerInfoId(t.getId());
            customerAllocation.setRecipientId(request.getUserId());
            customerAllocation.setType(1);
            customerAllocation.setRemark(t.getName() + "分配给后期：" + userNickNameMap.get(request.getUserId()));
        });
        this.customerAllocationService.saveOrUpdateBatch(customerAllocationList);

    }

    @Override
    public void backLoan(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        customerInfoList.forEach(t -> {
            t.setLoanStatus(0);
            t.setFollowCustomer(99);
            this.baseMapper.updateById(t);
        });

    }

    @Override
    public void publicLoan(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getLoanUser, null)
                    .set(CustomerInfo::getSigningStatus, 1)
                    .set(CustomerInfo::getFollowCustomer, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public void stateToAfter(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        customerInfoList.forEach(t -> {
            t.setAfterSaleStatus(2);
            t.setFollowCustomer(3);
            this.baseMapper.updateById(t);
        });

    }

    @Override
    public void distAfter(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        List<Long> userIds = customerInfoList.stream().map(CustomerInfo::getHandleUser).filter(ObjectUtil::isNotNull).collect(Collectors.toList());
        userIds.add(request.getUserId());
        Map<Long, String> userNickNameMap = this.sysUserService.getNickNameMap(userIds);
        List<CustomerAllocation> customerAllocationList = Lists.newArrayList();
        customerInfoList.forEach(t -> {
            t.setAfterUser(request.getUserId());
            t.setAfterSaleStatus(1);
            t.setFollowCustomer(4);
            this.baseMapper.updateById(t);
            CustomerAllocation customerAllocation = new CustomerAllocation();
            customerAllocationList.add(customerAllocation);
            customerAllocation.setCustomerInfoId(t.getId());
            customerAllocation.setRecipientId(request.getUserId());
            customerAllocation.setType(2);
            customerAllocation.setRemark(t.getName() + "分配给售后：" + userNickNameMap.get(request.getUserId()));
        });
        this.customerAllocationService.saveOrUpdateBatch(customerAllocationList);

    }

    @Override
    public void backAfter(CustomerRequest request) {
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery()
                .in(CustomerInfo::getId, request.getIds()));
        customerInfoList.forEach(t -> {
            t.setLoanStatus(1);
            t.setAfterSaleStatus(0);
            t.setFollowCustomer(99);
            this.baseMapper.updateById(t);
        });

    }

    @Override
    public void publicAfter(CustomerRequest request) {
        for (Long id : request.getIds()) {
            this.update(Wrappers.<CustomerInfo>lambdaUpdate()
                    .eq(CustomerInfo::getId, id)
                    .set(CustomerInfo::getAfterUser, null)
                    .set(CustomerInfo::getAfterSaleStatus, 1)
                    .set(CustomerInfo::getFollowCustomer, 99)
                    .set(CustomerInfo::getUpdateUser, SecurityUtils.getUserId())
            );
        }

    }

    @Override
    public CustomerFollowResponse getMessageTotal() {
        CustomerFollowResponse response = new CustomerFollowResponse();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<CustomerInfo> customerInfoList = this.baseMapper.selectList(Wrappers.<CustomerInfo>lambdaQuery().apply("1 = 1")
                .and(!SecurityUtils.isSuperAdmin(loginUser), t -> t.in(CustomerInfo::getHandleUser, loginUser.getBelongUserIds())
                .or().in(CustomerInfo::getLoanUser, loginUser.getBelongUserIds())
                .or().in(CustomerInfo::getAfterUser, loginUser.getBelongUserIds())));
        response.setDistNum((int) customerInfoList.stream().filter(t -> 0 == t.getFollowCustomer() && loginUser.getUserId().equals(t.getHandleUser())).count());
        response.setLoanNum((int) customerInfoList.stream().filter(t -> 2 == t.getFollowCustomer() && loginUser.getUserId().equals(t.getLoanUser())).count());
        response.setAfterNum((int) customerInfoList.stream().filter(t -> 4 == t.getFollowCustomer() && loginUser.getUserId().equals(t.getAfterUser())).count());
        response.setBirthdayNum((int) customerInfoList.stream().filter(t -> 1 == t.getAfterSaleStatus() && 0 == t.getFollowRemind() && (loginUser.getUserId().equals(t.getAfterUser()))).count());
        response.setRepaymentNum((int) customerInfoList.stream().filter(t -> 1 == t.getAfterSaleStatus() && 0 == t.getFollowRepayment() && (loginUser.getUserId().equals(t.getAfterUser()))).count());
        if (!SecurityUtils.isSuperAdmin(loginUser)) {
            if (!CollectionUtils.isEmpty(loginUser.getComponents()) && loginUser.getComponents().size() > 0) {
                if (loginUser.getComponents().contains(ComponentConstants.MENU_COMPONENT_INDEX_8)) {
                    response.setLoanToNum((int) customerInfoList.stream().filter(t -> 1 == t.getFollowCustomer()).count());
                }
                if (loginUser.getComponents().contains(ComponentConstants.MENU_COMPONENT_INDEX_9)) {
                    response.setAfterToNum((int) customerInfoList.stream().filter(t -> 3 == t.getFollowCustomer()).count());
                }
            }
        } else {
            response.setLoanToNum((int) customerInfoList.stream().filter(t -> 1 == t.getFollowCustomer()).count());
            response.setAfterToNum((int) customerInfoList.stream().filter(t -> 3 == t.getFollowCustomer()).count());
        }
        return response;
    }

    @Override
    public void backCustomerSnapshot(CustomerRequest request) {
        CustomerSnapshot customerSnapshot = this.customerSnapshotService.getById(request.getId());
        CustomerInfo customerInfo = this.baseMapper.selectById(request.getCustId());
        this.setColumn(customerInfo,customerSnapshot);
        this.edit(customerInfo);

    }

    private void setColumn(CustomerInfo customerInfo, CustomerSnapshot customerSnapshot) {
        for (String column : DictUtils.getColumnList()) {
            BeanUtil.setProperty(customerInfo, column, BeanUtil.getProperty(customerSnapshot, column));
        }
    }
}
